service 元件是可以把共用的行為或程式邏輯放在此元件中,並且透過相依注入的方法,使其他元件可以取用。
本次範例路徑如下圖,所使用為 app 資料夾底下的 app.module.ts 以及 feature.service.ts。
建立服務元件的起手式程式碼,不需要打 service,只要打元件名稱即可。
ng g s 元件名稱
EX. 自定義命名一個功能服務元件,只要在終端機輸入 ng g s feature
,就會建立一個名稱為 feature 的服務元件。
裡面預設程式碼如下,因為也是元件,所以結構看起來很相似。
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root",
})
export class FeatureService {
constructor() {}
}
其實服務元件也是一個類別,裡面放的內容只有兩個,屬性或是方法。
建立好 service
後,要回到 app.module.ts
中,注入 service
,Angular 10 很貼心的在我們新增 service 後會自動幫我們建立一個 providers
的屬性,其組成為陣列,代表可以放多個 service。
@NgModule({
declarations: [
AppComponent,
HomeComponent,
SecondComponent,
Home1Component,
Home2Component,
],
imports: [BrowserModule, AppRoutingModule, FormsModule], // 加入倒 imports
providers: [], // service 使用
bootstrap: [AppComponent],
})
雖然已經建立好,但還沒放入我們剛剛建立的 service
,所以要手動輸入剛剛建立的 service
名稱,所以只要把 featureService
放入陣列即可,放入後也會自動 import 到 app.module.ts
內。
因為 VScode 有內建 IntelliSense 功能,所以只要打關鍵字就會出現相對應的選項,選到想要的選項後按下 tab 就可以完成囉!
import { FeatureService } from './feature.service'; // service 新增
@NgModule({
declarations: [
AppComponent,
HomeComponent,
SecondComponent,
Home1Component,
Home2Component,
],
imports: [BrowserModule, AppRoutingModule, FormsModule], // 加入倒 imports
providers: [FeatureService], // service 使用
bootstrap: [AppComponent],
})
需要注意的地方是 providers
一定要把 service 元件註冊到 module 中,不然後續要相依性注入的時候會不能進行。
註冊完 service
後,最重要的就是要注入 service
,因為為了就是要共用其行為與邏輯。
假設在 service
裡面寫一個方法叫做 run()
,
export class FeatureService {
constructor() {}
run() {
console.log("featureService");
}
}
將 featureService
注入到 home.component.ts
中,因為註冊到父層就可以讓子層的 home1 跟 home2 元件使用。
首先在 constructor
建構式裡面宣告一個變數,這邊設定為 featureSvc,透過
TS 宣告型別為 featureService,在完成的過程中,import
也會自動完成。
在 constructor
上宣告一個 featureService
的屬性。
如果注入成功後,featureSvc
其屬性的值,就是 featureSvc
本身。
import { FeatureService } from './../feature.service';
export class HomeComponent implements OnInit {
featureSvc: FeatureService;
constructor(featureSvc: FeatureService) {
this.featureSvc = featureSvc;
}
當注入
featureService
時,透過建構式已經製作了一個實體物件,而且只會建構一次,所以得到的是唯一且可以共用的實體元件,所以未來需要共用的資料或是程式邏輯,都可以透過此元件來共享。
上方可看到要透過三行程式碼才能做出一個 featureService
的建構方式,但在 TS 有更簡潔的寫法,也就是加上其物件是否作為公開或是私有的方法,可改寫成下方這樣,
export class HomeComponent implements OnInit {
constructor(public featureSvc: FeatureService) {}// 一行解決
ngOnInit(): void {}
}
- public: 公開方法,任何程式碼都可以取用。
- private: 私有方法,只限於其物件下使用。
export class HomeComponent implements OnInit {
constructor(public featureSvc: FeatureService) {}// 一行解決
ngOnInit(): void {}
}
透過 ngOnInit()
為例,要使用在 service
建立的方法會變這樣寫:
export class HomeComponent implements OnInit {
constructor(public featureSvc: FeatureService) {}// 一行解決
ngOnInit(): void {
this.featureSvc.run(); // 呼叫在 service 建立的方法
}
}
可以看到方法已經從 feature.service.ts
被呼叫了!
以feature service為例,建立的時候 Angular CLI會預設
@Injectable({
providedIn: "root",
})
也就是宣告這個service預設的層級在整個應用程式。Angular會自動幫你實例化並且幫你注入。不需要在providers
的地方再宣告一次。除非你手動把這個預設的層級拿掉,想要只應用在某個模組之下
好的,感謝分享~